package com.sz.lucene;

import com.sz.pojo.frame.Tiku;
import com.sz.util.ToolDate;
import com.sz.util.ToolStr;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.StringField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.*;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.*;
import org.apache.lucene.search.highlight.*;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.StringReader;
import java.nio.file.Paths;
import java.util.LinkedList;
import java.util.List;

@Component
public class TikuIndex {
    private Directory dir = null;

    /**
     * 获取IndexWriter实例
     *
     * @return
     * @throws Exception
     */
    private IndexWriter getWriter(HttpServletRequest request) throws Exception {
        String dirPath = request.getServletContext().getRealPath("/");
        String contextPath = request.getServletContext().getContextPath();

        if (contextPath.length() <= 1) {
            contextPath = "/ROOT";
        }

        contextPath = contextPath.substring(1, contextPath.length());
        dirPath = dirPath.substring(0, dirPath.lastIndexOf(contextPath));

        dir = FSDirectory.open( Paths.get(dirPath + File.separator + "lucene") .toFile());

        SmartChineseAnalyzer analyzer = new SmartChineseAnalyzer();
        IndexWriterConfig iwc = new IndexWriterConfig(Version.LATEST,analyzer);
        IndexWriter writer = new IndexWriter(dir, iwc);
        return writer;
    }

    /**
     * 添加文章索引
     *
     */
    public void addIndex(HttpServletRequest request, Tiku tiku) throws Exception {
        IndexWriter writer = getWriter(request);
        Document doc = new Document();
        doc.add(new StringField("id", String.valueOf(tiku.getId()), Field.Store.YES));
        doc.add(new TextField("title", tiku.getQuesetion(), Field.Store.YES));
        doc.add(new StringField("time", ToolDate.formatTime(tiku.getTime(), "yyyy-MM-dd", null), Field.Store.YES));
        doc.add(new TextField("content", tiku.getAnswer(), Field.Store.YES));
        writer.addDocument(doc);
        writer.close();
    }

    /**
     * 更新文章索引
     *
     * @throws Exception
     */
    public void updateIndex(HttpServletRequest request, Tiku tiku) throws Exception {
        IndexWriter writer = getWriter(request);
        Document doc = new Document();
        doc.add(new StringField("id", String.valueOf(tiku.getId()), Field.Store.YES));
        doc.add(new TextField("title", tiku.getQuesetion(), Field.Store.YES));
        doc.add(new StringField("time", ToolDate.formatTime(tiku.getTime(), "yyyy-MM-dd", null), Field.Store.YES));
        doc.add(new TextField("content", tiku.getAnswer(), Field.Store.YES));
        writer.updateDocument(new Term("id", String.valueOf(tiku.getId())), doc);
        writer.commit();
        writer.close();
    }

    /**
     * 删除指定博客的索引
     *
     * @throws Exception
     */
    public void deleteIndex(HttpServletRequest request, String articleId) throws Exception {
        IndexWriter writer = getWriter(request);
        writer.deleteDocuments(new Term("id", articleId));
        writer.forceMergeDeletes(); // 强制删除
        writer.commit();
        writer.close();
    }

    /**
     * 查询博客信息
     *
     * @param q 查询关键字
     * @return
     * @throws Exception
     */
    public List<Tiku> searchArticle(HttpServletRequest request, String q) throws Exception {
        String dirPath = request.getServletContext().getRealPath("/");
        String contextPath = request.getServletContext().getContextPath();
        if (contextPath.length() <= 1) {
            contextPath = "/ROOT";
        }
        contextPath = contextPath.substring(1, contextPath.length());
        dirPath = dirPath.substring(0, dirPath.lastIndexOf(contextPath));
        dir = FSDirectory.open(Paths.get(dirPath + File.separator + "lucene").toFile());
        IndexReader reader = DirectoryReader.open(dir);
        IndexSearcher is = new IndexSearcher(reader);
        BooleanQuery  booleanQuery = new BooleanQuery ();
        SmartChineseAnalyzer analyzer = new SmartChineseAnalyzer();

        QueryParser parser = new QueryParser("title", analyzer);
        Query query = parser.parse(q);
        QueryParser parser2 = new QueryParser("content", analyzer);
        Query query2 = parser2.parse(q);

        booleanQuery.add(query, BooleanClause.Occur.SHOULD);
        booleanQuery.add(query2, BooleanClause.Occur.SHOULD);

        TopDocs hits = is.search(booleanQuery, 100);
        QueryScorer scorer = new QueryScorer(query);

        Fragmenter fragmenter = new SimpleSpanFragmenter(scorer);
        SimpleHTMLFormatter simpleHTMLFormatter = new SimpleHTMLFormatter("<font color='red'>", "</font>");

        Highlighter highlighter = new Highlighter(simpleHTMLFormatter, scorer);
        highlighter.setTextFragmenter(fragmenter);
        List<Tiku> blogList = new LinkedList<Tiku>();
        for (ScoreDoc scoreDoc : hits.scoreDocs) {
            Document doc = is.doc(scoreDoc.doc);
            Tiku tiku = new Tiku();
            tiku.setId(ToolStr.sToL(doc.get(("id")), -1));
            tiku.setTime(ToolDate.parseTime(doc.get("time"), "yyyy-MM-dd"));
            String title = doc.get("title");
            String content = (doc.get("content"));
            if (title != null) {
                TokenStream tokenStream = analyzer.tokenStream("title", new StringReader(title));
                String hTitle = highlighter.getBestFragment(tokenStream, title);
                if (ToolStr.isEmpty(hTitle)) {
                    tiku.setQuesetion(title);
                } else {
                    tiku.setQuesetion(hTitle);
                }
            }
            if (content != null) {
                TokenStream tokenStream = analyzer.tokenStream("content", new StringReader(content));
                String hContent = highlighter.getBestFragment(tokenStream, content);
                if (ToolStr.isEmpty(hContent)) {
                    if (content.length() <= 500) {
                        tiku.setAnswer(content);
                    } else {
                        tiku.setAnswer(content.substring(0, 500));
                    }
                } else {
                    tiku.setAnswer(hContent);
                }
            }
            blogList.add(tiku);
        }
        return blogList;
    }
}
